package handlers

import (
	"encoding/json"
	"net/http"
	"time"

	"homepage-backend/internal/config"

	"github.com/golang-jwt/jwt/v5"
)

type LoginRequest struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type LoginResponse struct {
	Token  string `json:"token"`
	Expire int64  `json:"expire"`
}

// AdminLoginHandler 处理后台登录
func AdminLoginHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusMethodNotAllowed)
		return
	}
	defer r.Body.Close()
	var req LoginRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		http.Error(w, "bad request", http.StatusBadRequest)
		return
	}
	if req.Username == config.GlobalConfig.AdminUser && config.VerifyPassword(config.GlobalConfig.AdminPassHash, req.Password) {
		expire := time.Now().Add(7 * 24 * time.Hour).Unix()
		claims := jwt.MapClaims{
			"username": config.GlobalConfig.AdminUser,
			"exp":      expire,
			"iat":      time.Now().Unix(),
			"jti":      generateJTI(),
		}
		token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
		signed, err := token.SignedString([]byte(config.GlobalConfig.JWTSecret))
		if err != nil {
			w.WriteHeader(http.StatusInternalServerError)
			return
		}
		resp := LoginResponse{
			Token:  signed,
			Expire: expire,
		}
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		if err := json.NewEncoder(w).Encode(resp); err != nil {
			w.WriteHeader(http.StatusInternalServerError)
		}
		return
	}
	http.Error(w, "unauthorized", http.StatusUnauthorized)
}

// generateJTI 生成唯一token ID
func generateJTI() string {
	return config.RandomString(16)
}

// AdminAuthMiddleware 校验JWT token
func AdminAuthMiddleware(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		tokenStr := r.Header.Get("Authorization")
		if len(tokenStr) > 7 && tokenStr[:7] == "Bearer " {
			tokenStr = tokenStr[7:]
		} else {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}
		token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
				return nil, jwt.ErrSignatureInvalid
			}
			return []byte(config.GlobalConfig.JWTSecret), nil
		})
		if err != nil || !token.Valid {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}
		next(w, r)
	}
}
